__author__ = 'Bao Liu'

import JsonParser
from unittest import TestCase
import pprint
import json

class TestSample(TestCase):
    def test_simple(self):
        ss = '''
{"widget": {
    "debug": "on",
    "window": {
        "title": "Sample Konfa\\btulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    },
    "image": {
        "src": "Images/Sun.png",
        "name": null,
        "hOffset": 2509999999999,
        "vOffset": 250.0,
        "alignment": "center"
    },
    "text": {
        "data": "Click Here",
        "size": 36,
        "style": true,
        "name": false,
        "hOffset": 250,
        "vOffset": 100,
        "alignment": "center",
        "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
    }
}}  '''
        a1 = JsonParser.JsonParser()
        a2 = JsonParser.JsonParser()
        a3 = JsonParser.JsonParser()

        a1.load(ss)
        d1 = a1.dumpDict()
        self.assertEqual(d1, json.loads(ss), 'JsonParser.load is not equal with json.loads')

        a2.loadDict(d1)
        a2.dumpJson('TestSample.json')
        a3.loadJson('TestSample.json')
        d3 = a3.dumpDict()
        self.assertEqual(d1, d3, 'TestSample Failed')
        self.assertEqual(d1, json.load(open('TestSample.json')), 'JsonParser.loadJson is not equal with json.load')

    def test_empty_strings(self):
        a1 = JsonParser.JsonParser()
        a1.load('""')
        self.assertEqual(a1.dumpDict(), u'')
        a1.load('[""]')
        self.assertEqual(a1.dumpDict(), [u''])

    def test_decoder_optimizations(self):
        a1 = JsonParser.JsonParser()
        a1.load('{   "key"    :    "value"    ,  "k":"v"    }')
        self.assertEqual(a1.dumpDict(), {"key":"value", "k":"v"})

    def test_circular_dict(self):
        d = {}
        d['a'] = d
        a1 = JsonParser.JsonParser()
        self.assertRaises(ValueError, a1.loadDict, d)

    def test_circular_composite(self):
        d = {}
        d['a'] = []
        d['a'].append(d)
        a1 = JsonParser.JsonParser()
        self.assertRaises(ValueError, a1.loadDict, d)

    def test_unsupported_type(self):
        a1 = JsonParser.JsonParser()
        self.assertRaises(ValueError, a1.loadDict, [set()])

    def test_pass1(self):
        JSON = r'''
[
    "JSON Test Pattern pass1",
    {"object with 1 member":["array with 1 element"]},
    {},
    [],
    -42,
    true,
    false,
    null,
    {
        "integer": 1234567890,
        "real": -9876.543210,
        "e": 0.123456789e-12,
        "E": 1.234567890E+34,
        "":  23456789012E66,
        "zero": 0,
        "one": 1,
        "space": " ",
        "quote": "\"",
        "backslash": "\\",
        "controls": "\b\f\n\r\t",
        "slash": "/ & \/",
        "alpha": "abcdefghijklmnopqrstuvwyz",
        "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
        "digit": "0123456789",
        "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
        "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
        "true": true,
        "false": false,
        "null": null,
        "array":[  ],
        "object":{  },
        "address": "50 St. James Street",
        "url": "http://www.JSON.org/",
        "comment": "// /* <!-- --",
        "# -- --> */": " ",
        " s p a c e d " :[1,2 , 3

,

4 , 5        ,          6           ,7        ],"compact": [1,2,3,4,5,6,7],
        "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
        "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
        "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
: "A key can be any string"
    },
    0.5 ,98.6
,
99.44
,

1066,
1e1,
0.1e1,
1e-1,
1e00,2e+00,2e-00
,"rosebud"]
'''
        a1 = JsonParser.JsonParser()
        a1.load(JSON)
        d1 = a1.dumpDict()
        dn = json.loads(JSON)
        self.assertEqual(d1, dn, 'JsonParser.load is not equal with json.loads')
        j1 = a1.dump()
        jn = json.dumps(dn)
        self.assertEqual(j1, jn, 'JsonParser.dump is not equal with json.dumps')
        a1.load(j1)
        d2 = a1.dumpDict()
        self.assertEqual(d1, d2)
        a1.loadDict(d2)
        d3 = a1.dumpDict()
        self.assertEqual(d1, d3)
        a1.dumpJson("TestPass1.json")
        a1.loadJson("TestPass1.json")
        d4 = a1.dumpDict()
        self.assertEqual(d1, d4)

    def test_pass2(self):
        JSON = r'''
[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
'''
        a1 = JsonParser.JsonParser()
        a1.load(JSON)
        d1 = a1.dumpDict()
        dn = json.loads(JSON)
        self.assertEqual(d1, dn, 'JsonParser.load is not equal with json.loads')
        j1 = a1.dump()
        jn = json.dumps(dn);
        self.assertEqual(j1, jn, 'JsonParser.dump is not equal with json.dumps')
        a1.load(j1)
        d2 = a1.dumpDict()
        self.assertEqual(d1, d2)
        a1.loadDict(d2)
        d3 = a1.dumpDict()
        self.assertEqual(d1, d3)
        a1.dumpJson("TestPass2.json")
        a1.loadJson("TestPass2.json")
        d4 = a1.dumpDict()
        self.assertEqual(d1, d4)

    def test_pass3(self):
        JSON = r'''
{
    "JSON Test Pattern pass3": {
        "The outermost value": "must be an object or array.",
        "In this test": "It is an object."
    }
}
'''
        a1 = JsonParser.JsonParser()
        a1.load(JSON)
        d1 = a1.dumpDict()
        dn = json.loads(JSON)
        self.assertEqual(d1, dn, 'JsonParser.load is not equal with json.loads')
        j1 = a1.dump()
        jn = json.dumps(dn);
        self.assertEqual(j1, jn, 'JsonParser.dump is not equal with json.dumps')
        a1.load(j1)
        d2 = a1.dumpDict()
        self.assertEqual(d1, d2)
        a1.loadDict(d2)
        d3 = a1.dumpDict()
        self.assertEqual(d1, d3)
        a1.dumpJson("TestPass3.json")
        a1.loadJson("TestPass3.json")
        d4 = a1.dumpDict()
        self.assertEqual(d1, d4)

    def test_invalid_escape(self):
        ss = '{"\o":5}'
        a1 = JsonParser.JsonParser()
        self.assertRaises(ValueError, a1.load, ss)

    def test_immutable_assignment(self):
        JSON = r'''
        [
                 true,
         false,
         null,
        [  ],
        {  },
         "50 St. James Street",
        {
        "integer": 1234567890,
        "real": -9876.543210,
        "e": 0.123456789e-12,
        "E": 1.234567890E+34
        }]
        '''

        a1 =  JsonParser.JsonParser()
        a1.load(JSON)
        d1 = a1.dumpDict()
        d1[0] = None
        d1[1] = True
        d1[2] = False
        d1[3] = {'d':'dd'}
        d1[4] = d1[3]
        d1[0] = {'cc':d1[3]}
        d1[3]['d'] = 'ee'
        d2 = a1.dumpDict()
        self.assertNotEqual(d1, d2, 'JsonParser.dumpDict return internal reference')
        a1[0] = None
        a1[1] = True
        a1[2] = False
        a1[3] = {'d': 'dd'}
        a1[4] = a1[3]
        a1[0] = {'cc':a1[3]}
        a1[3]['d'] = 'ee'
        a1[4]['d'] = 'ff'
        self.assertNotEqual(a1[3], a1[0]['cc'], 'JsonParser [] assign reference')
        self.assertNotEqual(a1[4], a1[0]['cc'], 'JsonParser [] assign reference')
        self.assertNotEqual(a1[4], a1[3], 'JsonParser [] assign reference')
        a1[3]['d'] = a1[3]
        self.assertRaises(ValueError, a1.dump)